import Cookies from 'js-cookie'
import _ from 'lodash'
import OSS from 'ali-oss'
class Utils {
  constructor() {
    this.KgNumber = /((^[1-9][0-9]{0,8})+(.?[0-9]{1,3})?$)|(^[0]+(.[0-9]{1,3})?$)/ // 最大10位数，3个小数
    this.notPositiveFloatPoint = /^((-\d+(\.\d+)?)|(0+(\.0+)?))$/ // 非正浮点数
  }

  getOSSFile () { // 阿里云服务
    // eslint-disable-next-line no-undef
    return new OSS({
      accessKeyId: 'LTAI4GGGjmP5CBtqvtpKCfdo',
      accessKeySecret: 'b5rDfYvYgoxZOWXn62DWSaxCuQHFr3',
      bucket: 'citi-ies-test',
      region: 'oss-cn-shenzhen'
    })
  }

  checkSpecialSymbol (data) { // 判断是否含特殊符号
    const flag = new RegExp('[`~!@#$^&*()=|{}\':;\',\\[\\].<>《》/?~！@#￥……&*（）——|{}【】‘；：”“\'。，、？]')
    return flag.test(data)
  }

  checkNumber (theObj) { // 验证是否为数字
    var reg = /^[+-]?\d+\.?\d*$/
    if (reg.test(theObj)) {
      return true
    }
    return false
  }

  checkNumberInteger (data, type) { // 是否为正/负整数 参数：（数字，类型：正/负）
    const positiveInteger = /^\+?[1-9][0-9]*$/ // 正整数
    // eslint-disable-next-line no-useless-escape
    const negativeInteger = /^\-[1-9][0-9]*$/ // 负整数
    if (type === '-') {
      if (negativeInteger.test(data)) {
        return true
      }
    }
    if (type === '+') {
      if (positiveInteger.test(data)) {
        return true
      }
    }
    return false
  }

  checkDecimalsPlaces (data, number) { // 验证小数位数 参数：（数字，位数）
    const reg = `^[+-]?\\d*\\.?\\d{0,${number}}$`
    if (new RegExp(reg).test(data)) {
      return true
    }
    return false
  }

  myTrim (x) { // 去前后空格
    return x.replace(/^\s+|\s+$/gm, '')
  }

  parseModle (name, modleObj) { // 模块输出
    this[name] = modleObj
    if (modleObj) {
      Object.keys(modleObj).forEach((key) => {
        this[name][key] = modleObj[key]
      })
    }
  }

  hexToRgba (hex, opacity) { // 十六进制color转rgba hex:十六进制色值=>#fffff opacity：透明的
    return 'rgba(' + parseInt('0x' + hex.slice(1, 3)) + ',' + parseInt('0x' + hex.slice(3, 5)) + ',' + parseInt('0x' + hex.slice(5, 7)) + ',' + opacity + ')'
  }

  hasDuplicates (arr, key) { // 判断是否存在重复的元素 根据数组对象中某个值的重复出现的判断
    const list = arr.map((item) => {
      return item[key]
    })
    return _.uniq(list).length !== list.length
  }

  colorRGB2Hex (color) { // rgba转十六进制
    var rgb = color.split(',')
    var r = parseInt(rgb[0].split('(')[1])
    var g = parseInt(rgb[1])
    var b = parseInt(rgb[2].split(')')[0])
    var hex = '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
    return hex
  }

  uniqArrayObj (arr, key) { // 数组对象去重 ，根据指定的字段去重
    if (arr.length > 0) {
      return arr.reduce((pre, cur) => {
        const filter = pre.map(item => {
          return item[key]
        })
        if (!filter.includes(cur[key])) {
          return pre.concat(cur)
        } else {
          return pre
        }
      }, [])
    } else {
      return []
    }
  }

  RGBtoHSV (color) { // 色值
    let h; let s
    const r = color[0]
    const g = color[1]
    const b = color[2]
    const min = Math.min(r, b)
    const max = Math.max(r, b)


    const v = max
    const delta = max - min
    if (max !== 0) {
      s = delta / max
    } else {
      // r = g = b = 0        // s = 0,v is undefined
      s = 0
      h = -1
      return [h, undefined]
    }
    if (r === max) {
      h = (g - b) / delta
    } else if (g === max) {
      h = 2 + (b - r) / delta
    } else {
      h = 4 + (r - g) / delta
    } // between magenta & cyan
    h *= 60 // degrees
    if (h < 0) {
      h += 360
    }
    if (isNaN(h)) {
      h = 0
    }
    return [h, v]
  };

  /**
 * Check if an element has a class
 * @param {HTMLElement} elm
 * @param {string} cls
 * @returns {boolean}
 */
  hasClass (ele, cls) {
    return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
  }

  /**
 * Add class to element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
  addClass (ele, cls) {
    if (!this.hasClass(ele, cls)) ele.className += ' ' + cls
  }

  /**
 * Remove class from element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
  removeClass (ele, cls) {
    if (this.hasClass(ele, cls)) {
      const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
      ele.className = ele.className.replace(reg, ' ')
    }
  }

  changeStr (str) {
    if (str.includes('/')) {
      const index = str.lastIndexOf('/')
      str = str.substring(index + 1, str.length)
      return str.charAt(0).toUpperCase() + str.slice(1)
    } else {
      return str.charAt(0).toUpperCase() + str.slice(1)
    }
  }

  KebabChangeCamel (str, key) { // kebab-case转Camel-case横杆转驼峰命名
    let result = ''
    if (str) {
      const list = str.split(key)
      result = list[0]
      if (list.length > 1) {
        list.map((item, key) => {
          if (key > 0) {
            result += this.firstUpperCase(item)
          }
        })
      }
    }
    return result
  }

  groupBy (array, f) { // 根据指定相同的属性值为条件进行分组
    const groups = {}
    array.forEach(function (o) {
      const group = JSON.stringify(f(o))
      groups[group] = groups[group] || []
      groups[group].push(o)
    })
    return Object.keys(groups).map(function (group) {
      return groups[group]
    })
  }

  // 方法调用： this.groupBy(this.form.tableData, function (item) { //按照这几个字段都相同的条件进行分组 'chargeProjectId', 'chargeUnitCode', 'operaRoutId', 'countryCode', 'destinationZoneId'
  //   return [item.chargeProjectId + item.chargeUnitCode + item.operaRoutId + item.countryCode + item.destinationZoneId]
  // })


  getLabelName (data, contex) { // 获取国际化语言
    const res = data.split('-')
    let str = ''
    if (res.length > 0) {
      res.map((item) => {
        if (Cookies.get('lang') === 'en') {
          str += contex.$t(item) + ' '
        } else {
          str += contex.$t(item)
        }
      })
    }
    return str
  }

  getJavaScriptModules (modulesFiles) { // modulesFiles 源文件
    return modulesFiles.keys().reduce((modules, modulePath) => {
      const moduleName = this.KebabChangeCamel(modulePath.replace(/^\.\/(.*)\.\w+$/, '$1'), '-')// 驼峰命名
      const value = modulesFiles(modulePath)
      modules[moduleName] = value.default
      return modules
    }, {})
  }

  getStrAfter (sourceSrt, target) { // 获取指定字符之后的内容
    const index = sourceSrt.lastIndexOf(target)
    const val = sourceSrt.substring(index + 1, sourceSrt.length)
    return val
  }

  getStrBefore (sourceSrt, target) { // 获取指定字符之前的内容
    const index = sourceSrt.lastIndexOf(target)
    return sourceSrt.substring(0, index)
  }

  firstUpperCase (str) { // 首字母大写
    const firstPathName = str[0].toUpperCase()
    const lastPathName = str.substring(1, str.length)
    return firstPathName + lastPathName
  }

  firstToLowerCase (str) { // 首字母小写
    const firstPathName = str[0].toLowerCase()
    const lastPathName = str.substring(1, str.length)
    return firstPathName + lastPathName
  }

  checkPhoneNumber (data) {
    // 手机号验证
    const phoneReg = /^1[3456789]\d{9}$/
    return phoneReg.test(data)
  }

  formatNumber (n) {
    n = n.toString()
    return n[1] ? n : '0' + n
  }

  formatDay (data) { // 日期
    const date = new Date(data)
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    return [year, month, day].map(this.formatNumber).join('-')
  }

  formatDateTime (data) { // 日期+时分秒
    const date = new Date(data)
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    const hours = date.getHours()
    const minutes = date.getMinutes()
    const seconds = date.getSeconds()
    return [year, month, day].map(this.formatNumber).join('-') + ' ' + [hours, minutes, seconds].map(this.formatNumber).join(':')
  }

  formatWeek (date) { // 星期几格式
    const nowDay = new Date(date)
    let days = nowDay.getDay()
    switch (days) {
      case 1:
        days = '星期一'
        break
      case 2:
        days = '星期二'
        break
      case 3:
        days = '星期三'
        break
      case 4:
        days = '星期四'
        break
      case 5:
        days = '星期五'
        break
      case 6:
        days = '星期六'
        break
      case 0:
        days = '星期日'
        break
    }
    return days
  }

  getNextMonth (date) {
    var arr = this.formatDay(new Date(date)).split('-')
    var year = arr[0] // 获取当前日期的年份
    var month = arr[1] // 获取当前日期的月份
    var day = arr[2] // 获取当前日期的日
    var days = new Date(year, month, 0)
    days = days.getDate() // 获取当前日期中的月的天数
    var year2 = year
    var month2 = parseInt(month) + 1
    if (month2 === 13) {
      year2 = parseInt(year2) + 1
      month2 = 1
    }
    var day2 = day
    var days2 = new Date(year2, month2, 0)
    days2 = days2.getDate()
    if (day2 > days2) {
      day2 = days2
    }
    if (month2 < 10) {
      month2 = '0' + month2
    }

    var t2 = year2 + '-' + month2 + '-' + day2
    return t2
  }

  getPrevMonth (date) {
    let d = new Date(date)
    d = +d - 1000 * 60 * 60 * 24 * 29
    d = new Date(d)
    var year = d.getFullYear()
    var mon = d.getMonth() + 1
    var day = d.getDate()
    const s = year + '-' + (mon < 10 ? ('0' + mon) : mon) + '-' + (day < 10 ? ('0' + day) : day)

    return s
  }

  /**
   * 求两个时间相隔几天
   * 以开始时间为基准，正数为大于开始时间，负数为小于开始时间；数值向上取整
   * @param {开始时间字符串: yyyy-MM-dd HH:mm:ss} startTime
   * @param {结束时间字符串: yyyy-MM-dd HH:mm:ss} endTime
   */
  getDaysApart (startTime, endTime) {
    var start = new Date(startTime)
    var end = new Date(endTime)
    var val = Math.abs(start.getTime() - end.getTime())
    var factor = 24 * 60 * 60 * 1000
    var days = val % factor === 0 ? parseInt(val / factor) : parseInt(val / factor) + 1
    return start > end ? -days : days
  }

  passwordCheck (data) { // 密码校验
    // 字母和数字组合
    const password = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$/
    if (password.test(data)) {
      return true
    } else {
      return false
    }
  }

  goback (cxt) {
    const matched = cxt.$route.matched
    if (matched.length > 1 && matched[matched.length - 2].path) {
      cxt.$router.push({ path: matched[1].path })
    }
  }

  deepClone (value) {
    const headToLowerCase = v => v.replace(/(^[A-Z])/g, (m, p1) => p1.toLowerCase())
    const is = (val, compareType) => {
      const type = Object.prototype.toString.call(val).replace(/^(\[object+\s)([\S]+)(\]$)/g, (m, p1, p2) => headToLowerCase(p2))
      return compareType ? (headToLowerCase(compareType) === type) : type
    }
    const type = is(value)
    const actions = {
      string: val => val.valueOf(),
      number: val => val.valueOf(),
      boolean: val => val.valueOf(),
      null: val => null,
      undefined: val => undefined,
      array: val => val.map(item => this.deepClone(item)),
      object: val => Object.entries(val).reduce((pre, [k, v]) => ({
        pre, [k]: this.deepClone(v)
      }), {}),
      regexp: (val) => new RegExp(val).valueOf(),
      date: (val) => new Date(val).valueOf(),
      htmlBodyElement: val => val.cloneNode(),
      default: val => val
    }
    const action = actions[type] || actions.default
    return action(value)
  }

  getUrlQuery (key) { // 获取url指定的key参数值
    const query = window.location.search.substring(1)
    const vars = query.split('&')
    for (let i = 0; i < vars.length; i++) {
      const pair = vars[i].split('=')
      if (pair[0] === key) {
        return pair[1]
      }
    }
    return (false)
  }

  getUrlQueryObj () { // 获取所有url参数转成对象
    const obj = {}
    const aParams = window.location.search.substr(1).split('&')
    if (aParams.length > 0 && aParams[0]) {
      for (let i = 0; i < aParams.length; i++) {
        var aParam = aParams[i].split('=')
        obj[aParam[0]] = aParam[1] ? decodeURI(aParam[1]) : ''
      }
    }
    return obj
  }

  getUrlRouter () { // 获取router的path
    const query = window.location.href
    const vars = query.split('?')
    const router = vars[0]
    const host = window.location.host
    return router.split(host)[1]
  }

  getFilterResult (arr, key, data) { // 过滤出数组对象中key=data的对象
    let filterResult = false
    if (arr.length > 0) {
      const result = arr.filter((item) => {
        return item[key] === data
      })
      if (result.length > 0) {
        filterResult = result[0]
      }
    }
    return filterResult
  }

  getRandomCode (length) { // 生成ID
    if (length > 0) {
      var data = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
      var nums = ''
      for (var i = 0; i < length; i++) {
        var r = parseInt(Math.random() * 61)
        nums += data[r]
      }
      return nums
    } else {
      return false
    }
  }

  getDifference (arr1, arr2, type = 'id') { // 获取两个数组对象中的差集
    const all = arr1.concat(arr2)
    return all.filter((p) => {
      const arr1State = arr1.some((item1) => {
        return p[type] === item1[type]
      })
      const arr2State = arr2.some((item1) => {
        return p[type] === item1[type]
      })
      if (!arr1State || !arr2State) {
        return p
      }
    })
  }

  getIntersection (arr1, arr2) { // 获取两个数组对象中的交集
    const all = arr1.concat(arr2)
    return all.filter((p) => {
      const arr1State = arr1.some((item1) => {
        return p.id === item1.id
      })
      const arr2State = arr2.some((item1) => {
        return p.id === item1.id
      })
      if (arr1State || arr2State) {
        return p
      }
    })
  }

  treeFind (tree, func) { // 节点查找
    for (const data of tree) {
      if (func(data)) return data
      if (data.children) {
        const res = this.treeFind(data.children, func)
        if (res) return res
      }
    }
    return null
  }

  /**
* @param {HTMLElement} element
* @param {string} className
*/
  toggleClass (element, className) {
    if (!element || !className) {
      return
    }
    let classString = element.className
    const nameIndex = classString.indexOf(className)
    if (nameIndex === -1) {
      classString += '' + className
    } else {
      classString =
        classString.substr(0, nameIndex) +
        classString.substr(nameIndex + className.length)
    }
    element.className = classString
  }

  /**
   * 替换所有指定的字符
   * @param {需要替换的字符串} str
   * @param {替换的字符} s1
   * @param {目标字符} s2
   */
  replaceAll (str, s1, s2) {
    return str.replace(new RegExp(s1, 'gm'), s2)
  }

  /**
   * 取字符串上某字符出现的次数
   * @param {源字符串} str
   * @param {字符} char
   */
  strCharPosition (str, char) {
    var pos
    var arr = []
    pos = str.indexOf(char)
    while (pos > -1) {
      arr.push(pos)
      pos = str.indexOf(char, pos + 1)
    }
    return arr.length
  }

  /**
   * 加法 小数点精度
   * @param {数字1} arg1
   * @param {数字2} arg2
   */
  accAdd (arg1, arg2) {
    let r1
    let r2
    try {
      r1 = arg1.toString().split('.')[1].length
    } catch (e) {
      r1 = 0
    }
    try {
      r2 = arg2.toString().split('.')[1].length
    } catch (e) {
      r2 = 0
    }
    const m = Math.pow(10, Math.max(r1, r2))
    return (arg1 * m + arg2 * m) / m
  }

  setExpandData (arr, index = 0) { // 设置expand递归tbale组件的数据
    index += 1
    if (arr.length > 0) {
      arr.map((item) => {
        if (item.list !== undefined && item.list.length > 0) {
          item.hasChildren = true
          item.index = index
          this.setExpandData(item.list, index)
        } else {
          item.index = index
          item.hasChildren = false
        }
      })
    }
    return arr
  }
}


export default new Utils()
